﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace MipsMachine
{
    public partial class Disassembler : Form
    {
        MipsProgram program;
        MipsMachine machine;

        bool running = false; //end of program

        public Disassembler(MipsProgram prog)
        {
            InitializeComponent();
            program = prog;
            disassemble();
            createRegisters();
        }

        private void disassemble()
        {
            uint counter = 0;
            HexView.Items.Clear();
            foreach (MipsInstruction ins in program.Program)
            {
                uint code = (uint)ins;
                String[] items = { ConvertToHexString(counter), ConvertToHexString(code), MipsDisassembler.disassemble(ins) };
                HexView.Items.Add(new ListViewItem(items));
                counter += 4;
            }
        }

        private void updateRegisters()
        {
            var values = Enum.GetValues(typeof(Register));
            for (int i = 0; i < values.Length; i++)
                updateItem((Register)values.GetValue(i));

        }

        private void createRegisters()
        {
            registerView.Items.Clear();
            var values = Enum.GetValues(typeof(Register));
            for (int i = 0; i < values.Length; i++)
                registerView.Items.Add(createItem((Register)values.GetValue(i)));

        }

        private ListViewItem createItem(Register register)
        {
            ListViewItem item = new ListViewItem("$" + register.ToString());
            uint value = 0;
            item.Name = register.ToString();
            item.SubItems.Add("0x" + ConvertToHexString(value));
            return item;
        }

        private void updateItem(Register register)
        {
            ListViewItem[] item = registerView.Items.Find(register.ToString(), false);
            if (item.Length > 0)
            {
                uint value = 0;
                if (machine != null)
                    value = (uint)machine.GetRegister(register);
                item[0].SubItems[1].Text = "0x" + ConvertToHexString(value);
            }
        }

        private string ConvertToHexString(uint value)
        {
            return Convert.ToString(value, 16).PadLeft(8, '0').ToUpper();
        }

        private void startDebuggingToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (machine != null)
                machine.Stop();
            machine = new MipsMachine(program);
            machine.Callback += value => { Output.Text += value; };
            machine.Initialize(4096);
            //HexView.Enabled = false;
            HexView.Items[0].Selected = true;
            updateRegisters();
        }

        private void nextToolStripMenuItem_Click(object sender, EventArgs e)
        {
            nextStep();
        }

        private void nextStep()
        {
            if (machine != null && machine.PC / 4 < HexView.Items.Count)
            {
                running = machine.Step();

                updateRegisters();
                HexView.Items[machine.PC / 4 - 1].Selected = false;
                if ((machine.PC / 4) < HexView.Items.Count)
                {
                    HexView.Items[machine.PC / 4].Selected = true;
                    HexView.EnsureVisible(machine.PC / 4);
                }
                if (!running)
                    HexView.Enabled = true;
            }
        }

        private void stopDebuggingToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (machine != null)
                machine.Stop();
            HexView.Enabled = true;
        }
    }
}
